Skip to content

docs(skills): record ComponentInput's five ADR-0049 tombstones in the plugin-development guide - #7647

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-7636-plugin-development-guide-tombstones
Sep 5, 2026
Merged

docs(skills): record ComponentInput's five ADR-0049 tombstones in the plugin-development guide#7647
os-zhuang merged 1 commit into
mainfrom
claude/issue-7636-plugin-development-guide-tombstones

Conversation

@claude

@claude claude Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Part of #7636 — this implements part 1 only, the half the domain:ui PM ruling dispatched. Part 2 (the gate question) is measured and filed as its own card, #7646, per that same ruling.

What was wrong

skills/objectui/guides/plugin-development.md documented five members of ComponentInput as ordinary writable optionals:

inputType?: string;    // Widget hint for the designer control
min?: number; max?: number; step?: number;   // numeric bounds
placeholder?: string;

All five are ADR-0049 retirement tombstones on the real type. The guide therefore taught a write that is a tsc error at the authoring site and a named parse refusal at runtime. This is the published skills tree — the guide is copied into users' repositories — so the blast radius is outside this repo, which is exactly where the tombstones' named refusal was bought to help.

The fence now records the tombstones as ?: never and points at description as the published remedy, in the real declaration's own wording.

⚠️ The green gate is NOT the evidence — read this part

pnpm check:skill-examples is green on this fence before and after, and that is the point. The fence declares its own local type ComponentInput alias instead of importing the published one, so the gate compiles a private copy and cannot compare it to the real declaration.

Evidence 1 — proven against the real declarations, with lit controls

Two instruments, both run against the built package, both agreeing:

tsc, importing the real ComponentInput and attempting each write. Run twice, once resolved to the published packages/types/dist/base.d.ts and once to packages/types/src/base.ts — identical results:

k_inputType.ts(5,3):   error TS2322: Type 'string' is not assignable to type 'undefined'.
k_min.ts(5,3):         error TS2322: Type 'number' is not assignable to type 'undefined'.
k_max.ts(5,3):         error TS2322: Type 'number' is not assignable to type 'undefined'.
k_step.ts(5,3):        error TS2322: Type 'number' is not assignable to type 'undefined'.
k_placeholder.ts(5,3): error TS2322: Type 'string' is not assignable to type 'undefined'.

Zod, ComponentInputSchema.safeParse per key — all five refused with code=invalid_type and the issue path naming the key, each carrying its own remedy string.

Lit control (both instruments): 2 of 2 genuinely-writable keys read as writable. advanced and description compile clean and parse clean. A control reading zero would have meant a dark instrument and the readings would have been discarded.

An earlier attempt at this instrument WAS dark — it resolved no module at all and reported all seven probes as failures. It was rebuilt with an explicit declaration path, and the --listFiles output was checked to confirm which declaration was actually read.

Evidence 2 — the two-arm control on the gate itself

Both arms had the mutation confirmed on disk by anchored grep counts, and were restored with git checkout HEAD -- PATH, verified by git diff HEAD empty and blob hash identical to the HEAD blob.

arm fence content result
A the wrong text, before this PR exit 0, greenSemantic phase: 13 of 13 ts fence(s) judged, 0 failed
corrected this PR exit 0, green — same line
B deliberately false: name: number where the real member is name: string; all five tombstones restored as writable; plus an invented member frobnicate on no type at all exit 0, green — same line

Arm B is the finding: the gate judged the fence (it is inside the 13 of 13, not skipped) and passed a snippet wrong about every member it names. That falsification is what justifies #7646.

⚠️ A missed prediction, reported as a miss. The first arm B left the corrected inputType?: never in place and added inputType?: string. Predicted green; it went redTS2300: Duplicate identifier plus TS2717. That is the gate correctly catching an internally invalid snippet, and it says nothing about drift. The arm was rebuilt as an internally consistent lie before it measured the intended thing.

Gates

All run on this PR's head — re-derived for the actual diff, not just the dispatched list.

gate verdict
check:skill-examples exit 0 — 13 of 13 ts fence(s) judged, 0 failed; Marked: 13 ts (floor 13), 70 json (floor 70) — floors unmoved
check:doc-snippets exit 0 — 452 of 452 block(s) judged, 0 failed
check:skills-paths exit 0 — 88/89 stated path(s) resolve across 20 guide file(s)
check:skill-eval-tokens exit 0 — Every must_contain token is taught by its own skill bundle
check:doc-fences exit 0
check:doc-types exit 0
check:control-bytes exit 0 — scanned 6246 tracked text file(s)
check:shell-escape-residue exit 0

check:skill-examples and check:doc-snippets each first returned exit 2, PRECONDITION NOT MET. That is NOT MEASURED — not a pass and not a red. Both were re-run after building what each names via its own --build-filter, and the verdicts above are from those re-runs.

Changeset: none owed, citing the gate's own verdict line — No source or published contract of a released package changed in this range, so no changeset is owed (1 file changed, 0 of them published source).

Line-count ratchet

Docs-only, net +7 lines, same number on both readings:

reading before after delta
skills/objectui/guides/plugin-development.md 446 453 +7
whole published bundle (all .md under skills/) 4495 4502 +7

The +7 buys the tombstone block: what ?: never means, that it is a tsc error and a named Zod refusal, why the keys were never published (the serializer's six forwarded keys), and the description remedy. It also carries the one distinction a reader can get wrong in a costly direction — that BaseSchema.placeholder, the node-level prop, is a different key and is unaffected. The old text was 4 lines of writable-optional declarations; nothing else was rewrapped or re-flowed to buy those lines.

Clause-② determination

Clause-②: no — my own determination, and it agrees with the PM's. The diff is one markdown file in the published skills tree. No schema key moves, no export moves, no accept/reject behaviour moves: the ?: never tombstones and the retirementTombstone() refusals already exist and already behave this way. This PR only stops the documentation from contradicting them.

Landing route

skills/** is a governed surface — agent drafts, human merges. Opened as a draft, and it is not enqueued and should not be. Parking for a human is the expected outcome here, not a failure.

Out of scope, filed not fixed

🤖 Generated with Claude Code

https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3


Generated by Claude Code

… plugin guide (objectui#7636)

`skills/objectui/guides/plugin-development.md` documented `inputType`, `min`,
`max`, `step` and `placeholder` as ordinary writable optionals on
`ComponentInput`. All five are ADR-0049 retirement tombstones on the real type:
`?: never` on the interface in `packages/types/src/base.ts` and a
`retirementTombstone()` named refusal on the Zod mirror in
`packages/types/src/zod/base.zod.ts`. The guide therefore taught a write that is
a `tsc` error at the authoring site and a named parse refusal at runtime.

This is the PUBLISHED skills tree — the guide is copied into users'
repositories — so the blast radius is outside this repo, which is exactly where
the tombstones' named refusal was bought to help.

The fence now records the tombstones as `?: never` and points at `description`
as the published remedy, matching the real declaration's own wording.

Verified against the real declarations rather than against the gate:
`check:skill-examples` is green on this fence both before and after, because
the snippet re-declares `ComponentInput` locally instead of importing it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
@claude

claude Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

受管面:请求 GOVERNED_APPROVERS 批准 — @hotlong / @os-zhuang

这张 PR 只改 skills/objectui/guides/plugin-development.md,落在 GOVERNED_SURFACESskills-catalog(skills/**,已发布的 skills 目录)。守卫脚本自己的 --test 判定逐字如下:

⛔ GOVERNED — 1 of 1 path(s) are on a governed surface
One governed path governs the WHOLE pull request — proportion is not a question.
⛔ Do not flip it ready, enqueue it, or arm auto-merge. Park it as a DRAFT and leave the merge to the maintainer; a human merge IS the review record for a governed surface.

所以本席不翻 ready、不入队、不开 auto-merge,并且按第五条禁令不会自己留那条批准——本仓所有 agent 席位共用一个 GitHub 身份,GOVERNED_APPROVERS 只是技术控制,真正兜底的是那条规范。

现状:CI 全绿,内容已就绪

28 条 check run,25 success + 3 skipped,零红(逐条枚举,未读聚合值)。head 3c881ddc

⭐ 按 2026-09-04 维护者裁定,批准留在哪个 commit 上都算、后续 push 不需要重新批——所以这条批准现在给就有效,不必等我再推什么。

需要你看的是什么

改的是一个 os:check fence:把 inputType / min / max / step / placeholder 从「普通可写可选项」改成记录成 ADR-0049 退役墓碑,并指向 description 作为已发布的替代。净 +7 行(文件 446→453,整棵已发布 bundle 4495→4502),没有为了凑行数重排任何段落。

这个指南会被复制进使用者的仓库,所以它教错的写法,爆炸半径在本仓之外——正是墓碑那套具名拒绝当初要保护的地方。

⚠️ 一件必须一起知道的事:门禁看不见这次修正对不对

check:skill-examples 在这个 fence 上修前修后都绿。不是它跳过了这个 fence——它判了,13 个里的 1 个。它绿是因为片段自己声明了一份本地 type ComponentInput,门禁编译的是那份私有副本,没法和真实声明比对

所以绿门禁不是这次修正正确的证据,我们也没拿它当证据。证据是另外两套仪器:tsc 导入真实 ComponentInput 逐键写入(对 dist/base.d.tssrc/base.ts 各跑一次,--listFiles 确认实际读的是哪份声明),五个键全 TS2322;Zod safeParse 五个键全 code=invalid_type亮对照 2/2:advanceddescription 两个真可写的键在两套仪器里都通过。

同时对门禁本身做了双臂对照:一个内部自洽但每个成员都说谎的 fence(name: number、五个墓碑全改回可写、外加一个不存在于任何类型的 frobnicate)——exit 0,绿。这就是 #7646 立卡的依据(全仓 26 处 fence 重声明已发布类型,横跨两个门禁)。

⇒ 也就是说,这个 fence 的正确性目前只能靠人看,门禁给不了你保证。这是请你批准时应该知道的事,不是可以略过的细节。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 5, 2026 06:07
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 5, 2026
Merged via the queue into main with commit 0916388 Sep 5, 2026
30 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-7636-plugin-development-guide-tombstones branch September 5, 2026 06:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants